#include "TaskStateMachine.h"

#include <QDateTime>
#include <QDebug>
#include <QTimer>

#include "ConstData.h"
#include "ConstNames.h"
#include "DeviceManager.h"

const int COMPOSITE_TASK_SPIKE_RECOVERY = 14;
const int COMPOSITE_TASK_ANALYSIS = 15;

// 错误去重静态成员定义
QMap<QString, qint64> TaskStateMachine::s_lastErrorTime;

// 使用全局常量定义操作名称映射
const QMap<AtomicOperation, QString> TaskStateMachine::OPERATION_NAMES = {
    {AtomicOperation::IDLE, OperationNames::SYSTEM_IDLE},
    {AtomicOperation::PREPROCESS, OperationNames::PRE_PROCESS},
    {AtomicOperation::ALGAE_REMOVAL, OperationNames::PRE_ALGAE_REMOVAL},
    {AtomicOperation::ZERO_CHECK, OperationNames::NORMAL_ZERO_CHECK},
    {AtomicOperation::STD_CHECK, OperationNames::NORMAL_STD_CHECK},
    {AtomicOperation::CALIB_FULL, OperationNames::NORMAL_CALIB_FULL},
    {AtomicOperation::SPIKE_INTAKE, OperationNames::SPIKE_INTAKE},
    {AtomicOperation::SPIKE_ANALYSIS, OperationNames::NORMAL_ANALYSIS},  // 加标测量用常规测量
    {AtomicOperation::SPIKE_DRAIN, OperationNames::COMMON_STOP},         // 加标仪停止加标就是排水
    {AtomicOperation::SAMPLE_INTAKE, OperationNames::SAMPLE_INTAKE},
    {AtomicOperation::ANALYSIS, OperationNames::NORMAL_ANALYSIS},
    {AtomicOperation::SAMPLE_DRAIN, OperationNames::SAMPLE_DRAIN_PRE},
    {AtomicOperation::CLEAN, OperationNames::NORMAL_CLEAN},
    {AtomicOperation::STOP_DEVICE, OperationNames::COMMON_STOP},
    {AtomicOperation::PRE_SPIKE_VALVE_OPEN, OperationNames::PRE_STEP_SPIKE_VALVE_OPEN},
    {AtomicOperation::PRE_SPIKE_VALVE_CLOSE, OperationNames::PRE_STEP_SPIKE_VALVE_CLOSE},
    {AtomicOperation::SPIKE_RECOVERY_FULL, OperationNames::SPIKE_RECOVERY_START},
};

TaskStateMachine::TaskStateMachine(QObject* parent)
    : QObject(parent),
      m_isRunning(false),
      m_currentTaskCode(0),
      m_currentStepIndex(-1),
      m_currentStepState(StepState::COMPLETED),
      m_stepTimer(nullptr),
      m_waitTimer(nullptr),
      m_monitorTimer(nullptr)
{
    // 创建定时器
    m_stepTimer = new QTimer(this);
    m_stepTimer->setSingleShot(true);
    connect(m_stepTimer, &QTimer::timeout, this, &TaskStateMachine::onStepTimeout);

    m_waitTimer = new QTimer(this);
    m_waitTimer->setSingleShot(true);
    connect(m_waitTimer, &QTimer::timeout, this, &TaskStateMachine::onWaitTimeout);

    m_monitorTimer = new QTimer(this);
    m_monitorTimer->setInterval(1000);  // 1秒检查一次
    connect(m_monitorTimer, &QTimer::timeout, this, &TaskStateMachine::checkStepCompletion);

    // 定义内置任务
    defineBuiltinTasks();
}

TaskStateMachine::~TaskStateMachine() { stop(); }

void TaskStateMachine::start()
{
    m_isRunning = true;
    qDebug() << "状态机已启动";
}

void TaskStateMachine::stop()
{
    if (m_isRunning) {
        // 清理当前任务状态
        cleanupCurrentTask();
        // 停止状态机
        m_isRunning = false;
        qDebug() << "状态机已停止";
    }
}

void TaskStateMachine::defineCompositeTask(int taskCode, const CompositeTask& task)
{
    m_compositeTasks[taskCode] = task;
    qDebug() << "定义复合任务" << taskCode << ":" << task.name;
}

bool TaskStateMachine::hasCompositeTask(int taskCode) const
{
    return m_compositeTasks.contains(taskCode);
}

CompositeTask TaskStateMachine::getCompositeTask(int taskCode) const
{
    return m_compositeTasks.value(taskCode, CompositeTask());
}

QList<int> TaskStateMachine::getAvailableTasks() const { return m_compositeTasks.keys(); }

bool TaskStateMachine::executeTask(int taskCode)
{
    if (!m_isRunning) {
        qDebug() << "状态机未启动";
        return false;
    }

    if (m_currentStepIndex >= 0) {
        qDebug() << "当前有任务正在执行";
        return false;
    }

    if (!m_compositeTasks.contains(taskCode)) {
        qDebug() << "未找到任务定义" << taskCode;
        return false;
    }

    // 清除之前的执行条件
    clearConditions();

    m_currentTask = m_compositeTasks[taskCode];
    m_currentTaskCode = taskCode;
    m_currentStepIndex = 0;

    qDebug() << "开始执行任务" << taskCode << ":" << m_currentTask.name;
    emit taskStarted(taskCode, m_currentTask.name);

    executeCurrentStep();
    return true;
}

bool TaskStateMachine::executeAtomicOperation(AtomicOperation operation, const QStringList& devices)
{
    if (!m_isRunning) {
        qDebug() << "状态机未启动";
        return false;
    }

    if (m_currentStepIndex >= 0) {
        qDebug() << "当前有任务正在执行";
        return false;
    }

    // 创建临时单步任务
    OperationStep step(operation, devices);
    step.description = getOperationName(operation);

    CompositeTask singleTask("单步操作");
    singleTask.steps.append(step);

    m_currentTask = singleTask;
    m_currentTaskCode = static_cast<int>(operation);
    m_currentStepIndex = 0;

    qDebug() << "执行原子操作" << getOperationName(operation);
    emit taskStarted(m_currentTaskCode, step.description);

    executeCurrentStep();
    return true;
}

void TaskStateMachine::cleanupCurrentTask()
{
    if (m_currentStepIndex >= 0) {
        m_stepTimer->stop();
        m_waitTimer->stop();
        m_monitorTimer->stop();
        m_currentTask = CompositeTask();
        m_currentTaskCode = 0;
        m_currentStepIndex = -1;
        m_currentStepState = StepState::COMPLETED;
        m_operatedDevices.clear();
        emit taskFinished(m_currentTaskCode);
    }
}

void TaskStateMachine::stopAllDevices()
{
    auto deviceManager = DeviceManager::instance();
    deviceManager->stopAllDevices();
}

void TaskStateMachine::stopCurrentTask()
{
    qDebug() << "停止当前任务";
    stopAllDevices();
    cleanupCurrentTask();
}

QString TaskStateMachine::getCurrentTaskName() const
{
    return (m_currentStepIndex >= 0) ? m_currentTask.name : QString();
}

int TaskStateMachine::getCurrentStepIndex() const { return m_currentStepIndex; }

int TaskStateMachine::getTotalSteps() const
{
    return (m_currentStepIndex >= 0) ? m_currentTask.steps.size() : 0;
}

QString TaskStateMachine::getCurrentStepDescription() const
{
    if (m_currentStepIndex >= 0 && m_currentStepIndex < m_currentTask.steps.size()) {
        return m_currentTask.steps[m_currentStepIndex].description;
    }
    return QString();
}

AtomicOperation TaskStateMachine::getCurrentOperation() const
{
    if (m_currentStepIndex >= 0 && m_currentStepIndex < m_currentTask.steps.size()) {
        return m_currentTask.steps[m_currentStepIndex].operation;
    }
    return AtomicOperation::IDLE;
}

QString TaskStateMachine::getOperationName(AtomicOperation operation)
{
    return OPERATION_NAMES.value(operation, "未知操作");
}

void TaskStateMachine::setCondition(const QString& key, bool value)
{
    m_conditions[key] = value;
    qDebug() << "设置条件" << key << "=" << value;
}

bool TaskStateMachine::getCondition(const QString& key) const
{
    return m_conditions.value(key, true);  // 默认为true
}

void TaskStateMachine::clearConditions()
{
    m_conditions.clear();
    qDebug() << "清除所有条件";
}

void TaskStateMachine::onStepTimeout() { handleTimeout("步骤执行", "执行", "跳过执行超时的步骤"); }

void TaskStateMachine::onWaitTimeout()
{
    handleTimeout("等待设备操作完成", "等待", "跳过等待超时的步骤");
}

void TaskStateMachine::handleTimeout(const QString& timeoutType, const QString& failurePrefix,
                                     const QString& skipMessage)
{
    if (m_currentStepIndex >= 0 && m_currentStepIndex < m_currentTask.steps.size()) {
        const OperationStep& step = m_currentTask.steps[m_currentStepIndex];

        qWarning() << timeoutType << "超时";
        emit stepTimeout(m_currentStepIndex);

        if (step.abortOnError) {
            // 终止任务
            emit taskFailed(m_currentTaskCode,
                            QString("%1%2超时").arg(failurePrefix).arg(step.description));
            stopCurrentTask();
        } else {
            // 跳过此步骤，继续下一步
            qDebug() << skipMessage << m_currentStepIndex << "，继续执行";
            m_stepTimer->stop();
            m_waitTimer->stop();
            m_monitorTimer->stop();
            emit stepCompleted(m_currentStepIndex);
            executeNextStep();
        }
    }
}

void TaskStateMachine::checkStepCompletion()
{
    if (m_currentStepIndex < 0 || m_currentStepIndex >= m_currentTask.steps.size()) {
        m_monitorTimer->stop();
        return;
    }

    const OperationStep& step = m_currentTask.steps[m_currentStepIndex];

    if (m_currentStepState == StepState::PREPARING) {
        // 尝试执行操作
        QStringList actualOperatedDevices;
        QString errorMessage;
        bool executeSuccess =
            executeAtomicOperationInternal(step, actualOperatedDevices, errorMessage);

        if (executeSuccess) {
            // 执行成功，进入执行状态
            m_operatedDevices = actualOperatedDevices;
            m_currentStepState = StepState::EXECUTING;
            emit operationStarted(step.operation, actualOperatedDevices);
            qInfo() << "步骤" << m_currentStepIndex
                    << "操作启动成功，实际操作设备:" << actualOperatedDevices << "，进入执行状态";
        } else {
            // 执行失败（所有设备都无法执行），继续等待下次重试
            // 使用错误去重机制，避免相同错误重复打印
            QString errorKey =
                QString("步骤%1暂时无法执行:%2").arg(m_currentStepIndex).arg(errorMessage);
            qint64 currentTime = QDateTime::currentMSecsSinceEpoch();

            // 检查是否需要打印错误（距离上次打印超过冷却期）
            if (!s_lastErrorTime.contains(errorKey) ||
                (currentTime - s_lastErrorTime[errorKey]) > ERROR_COOLDOWN_MS) {
                qWarning() << errorKey;
                s_lastErrorTime[errorKey] = currentTime;
            }
        }
    } else if (m_currentStepState == StepState::EXECUTING) {
        // 检查已操作的设备是否变繁忙
        if (areAllDevicesBusy(m_operatedDevices)) {
            m_stepTimer->stop();
            qInfo() << "步骤" << m_currentStepIndex << "已操作设备变繁忙，操作执行成功";
            emit operationCompleted(step.operation);

            // 检查是否需要等待条件
            if (step.waitTimeout > 0) {
                // 进入等待状态
                m_currentStepState = StepState::WAITING;
                qInfo() << "步骤" << m_currentStepIndex << "开始等待设备达到状态:"
                        << (step.waitForStatus.isEmpty() ? "空闲" : step.waitForStatus);

                // 启动等待超时定时器
                m_waitTimer->start(step.waitTimeout * 1000);
            } else {
                // 无需等待，直接完成
                m_currentStepState = StepState::COMPLETED;
                emit stepCompleted(m_currentStepIndex);
                executeNextStep();
            }
        }
    } else if (m_currentStepState == StepState::WAITING) {
        // 检查等待设备操作完成是否满足
        QStringList completedDevices;
        bool conditionMet = checkDeviceCondition(completedDevices);
        if (conditionMet) {
            m_waitTimer->stop();
            m_currentStepState = StepState::COMPLETED;
            qInfo() << "步骤" << m_currentStepIndex
                    << "等待设备操作完成，已完成设备:" << completedDevices << "，步骤完成";
            emit stepCompleted(m_currentStepIndex);
            executeNextStep();
        }
    }
}

void TaskStateMachine::executeCurrentStep()
{
    if (m_currentStepIndex < 0 || m_currentStepIndex >= m_currentTask.steps.size()) {
        return;
    }

    const OperationStep& step = m_currentTask.steps[m_currentStepIndex];

    // 检查条件步骤是否应该执行
    if (!step.conditionKey.isEmpty()) {
        bool shouldExecute = getCondition(step.conditionKey);
        qDebug() << "条件步骤" << m_currentStepIndex << ":" << step.description << "条件"
                 << step.conditionKey << "=" << shouldExecute;

        if (!shouldExecute) {
            qDebug() << "跳过条件步骤" << m_currentStepIndex;
            emit stepStarted(m_currentStepIndex, step.description + " (跳过)");
            emit stepCompleted(m_currentStepIndex);
            executeNextStep();
            return;
        }
    }

    qDebug() << "执行步骤" << m_currentStepIndex << ":" << step.description;

    emit stepStarted(m_currentStepIndex, step.description);

    // 设置步骤状态为准备阶段
    m_currentStepState = StepState::PREPARING;
    m_operatedDevices.clear();

    // executeTimeout包含3个步骤：等待设备空闲→执行操作→判断设备繁忙
    m_stepTimer->start(step.executeTimeout * 1000);

    // 启动监控定时器（会定期尝试执行和检查状态）
    m_monitorTimer->start();
}

void TaskStateMachine::executeNextStep()
{
    m_currentStepIndex++;

    if (m_currentStepIndex >= m_currentTask.steps.size()) {
        // 任务完成
        qDebug() << "任务" << m_currentTask.name << "执行完成";
        emit taskCompleted(m_currentTaskCode);
        cleanupCurrentTask();
    } else {
        // 继续执行下一步
        executeCurrentStep();
    }
}

bool TaskStateMachine::executeAtomicOperationInternal(const OperationStep& step,
                                                      QStringList& operatedDevices,
                                                      QString& errorMessage)
{
    QStringList targetDevices = step.targetDevices;
    if (targetDevices.isEmpty()) {
        targetDevices = getDeviceNames();
    }

    operatedDevices.clear();
    QString operationName = getOperationName(step.operation);
    QStringList busyDevices;
    QStringList errorDevices;

    // 逐个设备检查并执行操作
    for (const QString& deviceName : targetDevices) {
        auto helper = DeviceManager::instance()->getDeviceHelper(deviceName);
        if (!helper) {
            errorDevices.append(QString("%1(不存在)").arg(deviceName));
            continue;
        }
        if (!helper->isEnabled()) {
            errorDevices.append(QString("%1(未启用)").arg(deviceName));
            continue;
        }
        if (!helper->isIdle() && step.operation != AtomicOperation::SPIKE_DRAIN) {
            // 排除加标仪排水操作，因为加标仪器停止加标就是排水，而这时候加标仪器是非空闲状态的。
            busyDevices.append(deviceName);
            continue;
        }

        // 设备空闲，尝试执行操作
        qint16 operateCode = helper->getOperateMap().value(operationName, -1);
        if (operateCode != -1) {
            helper->control(operateCode);
            operatedDevices.append(deviceName);
            qDebug() << "设备" << deviceName << "执行操作" << operationName;
        } else {
            errorDevices.append(QString("%1(不支持操作%2)").arg(deviceName, operationName));
        }
    }

    // 构建错误消息
    QStringList errorMessages;
    if (!busyDevices.isEmpty()) {
        errorMessages.append(QString("繁忙设备: %1").arg(busyDevices.join(", ")));
    }
    if (!errorDevices.isEmpty()) {
        if (step.abortOnError) {
            // 如果步骤要求出错时终止任务，直接返回错误
            errorMessage = QString("设备操作失败: %1").arg(errorDevices.join(", "));
            qDebug() << errorMessage;
            emit taskFailed(m_currentTaskCode, errorMessage);
            stopCurrentTask();
            return false;  // 终止任务
        }
        errorMessages.append(QString("错误设备: %1").arg(errorDevices.join(", ")));
    }

    if (!errorMessages.isEmpty()) {
        errorMessage = errorMessages.join("; ");
    }

    // 如果有设备成功执行操作，就认为部分成功
    if (!operatedDevices.isEmpty()) {
        if (!busyDevices.isEmpty() || !errorDevices.isEmpty()) {
            qDebug() << "部分设备执行成功，操作设备:" << operatedDevices
                     << "，问题:" << errorMessage;
        }
        return true;
    } else {
        // 没有任何设备成功执行
        return false;
    }
}

bool TaskStateMachine::areAllDevicesIdle(const QStringList& devices) const
{
    for (const QString& deviceName : devices) {
        auto helper = DeviceManager::instance()->getDeviceHelper(deviceName);
        if (helper && helper->isEnabled() && !helper->isIdle()) {
            return false;
        }
    }
    return true;
}

bool TaskStateMachine::areAllDevicesBusy(const QStringList& devices) const
{
    for (const QString& deviceName : devices) {
        auto helper = DeviceManager::instance()->getDeviceHelper(deviceName);
        if (!helper || !helper->isEnabled() || helper->isIdle()) {
            return false;
        }
    }
    return true;
}

bool TaskStateMachine::checkDeviceCondition(QStringList& completedDevices)
{
    // 遍历已操作的设备，检查状态
    QStringList errorDevices;
    QStringList incompleteDevices;
    QStringList localCompletedDevices;
    const OperationStep& step = m_currentTask.steps[m_currentStepIndex];

    for (const QString& deviceName : m_operatedDevices) {
        auto helper = DeviceManager::instance()->getDeviceHelper(deviceName);
        if (!helper || !helper->isEnabled()) {
            continue;  // 跳过不存在或未启用的设备
        }

        // 1. 检查错误码
        if (helper->hasError()) {
            errorDevices.append(deviceName);
            if (step.abortOnError) {
                // 如果有错误且步骤要求出错时终止任务
                qDebug() << "设备" << deviceName << "发生错误，终止任务";
                emit taskFailed(m_currentTaskCode,
                                QString("设备%1发生错误，无法继续执行").arg(deviceName));
                stopCurrentTask();
                return false;  // 终止任务，不满足等待条件
            }
            continue;  // 设备有错误但不影响其他设备，继续检查下一个
        }

        // 2. 检查设备是否达到目标状态
        bool targetStatusReached = false;
        if (step.waitForStatus.isEmpty() || step.waitForStatus == "idle") {
            // 等待空闲状态（默认行为）
            targetStatusReached = helper->isIdle();
        } else {
            // 等待指定状态
            targetStatusReached =
                helper->getStatusName(helper->getDeviceData().status) == step.waitForStatus;
        }

        if (!targetStatusReached) {
            incompleteDevices.append(deviceName);
            continue;  // 设备还未达到目标状态，继续检查下一个
        }

        // 设备正常完成
        localCompletedDevices.append(deviceName);
    }
    // 判断条件：至少有一个设备正常完成 且 所有未出错的设备都已完成
    // 策略：排除错误设备，只要剩余设备全部完成就算成功
    if (!localCompletedDevices.isEmpty() && incompleteDevices.isEmpty()) {
        completedDevices = localCompletedDevices;
        qDebug() << "错误设备:" << errorDevices;
        qDebug() << "完成设备:" << localCompletedDevices << "，无未完成设备，满足等待条件";
        return true;
    }

    // 特殊情况：所有启用设备都有错误，但步骤设置为不停机，则继续执行
    if (!errorDevices.isEmpty() && localCompletedDevices.isEmpty() && incompleteDevices.isEmpty() &&
        !step.abortOnError) {
        completedDevices = QStringList();  // 没有正常完成的设备
        qDebug() << "所有设备都有错误但步骤设置为不停机，继续执行任务";
        qDebug() << "错误设备:" << errorDevices;
        return true;
    }

    // 还有设备在忙碌，继续等待
    return false;
}

QStringList TaskStateMachine::getDeviceNames() const
{
    QStringList normalDevices;
    for (const QString& deviceName : DEVICE_NAMES) {
        if (DEVICE_MAP.value(deviceName).deviceType != DeviceType_wcs) {
            normalDevices.append(deviceName);
        }
    }
    return normalDevices;
}

void TaskStateMachine::defineBuiltinTasks()
{
    defineAnalysisTask();
    defineSpikeRecoveryTask();

    qDebug() << "内置复合任务定义完成，共" << m_compositeTasks.size() << "个复合任务";
    qDebug() << "其他任务将作为单步操作执行";
}

void TaskStateMachine::defineAnalysisTask()
{
    // 水样测量任务：预处理 → 采样仪抽水 → 水样测量 → (条件)采样仪排水
    CompositeTask analysisTask("水样测量任务");
    analysisTask.description = "执行标准的水样测量流程，包含采样仪操作";

    // 步骤1：预处理（执行预处理 + 等待预处理完成）
    OperationStep preprocessStep(AtomicOperation::PREPROCESS);
    preprocessStep.targetDevices = DeviceNames::getDeviceNamesByType(DeviceType_ycl);
    preprocessStep.description = "预处理准备";
    preprocessStep.abortOnError = true;
    preprocessStep.waitTimeout = 60 * 60;  // 等待预处理完成超时：1小时
    analysisTask.steps.append(preprocessStep);

    // 步骤2：采样仪抽水（简单操作）
    OperationStep intakeStep(AtomicOperation::SAMPLE_INTAKE);
    intakeStep.targetDevices = DeviceNames::getDeviceNamesByType(DeviceType_sample);
    intakeStep.description = "采样仪抽水";
    analysisTask.steps.append(intakeStep);

    // 步骤3：水样测量（执行水样测量 + 等待水样测量完成）
    OperationStep analysisStep(AtomicOperation::ANALYSIS);
    analysisStep.targetDevices = DeviceNames::getDeviceNamesByType(DeviceType_normal);
    analysisStep.description = "水样测量";
    analysisStep.waitTimeout = 60 * 60;  // 等待测量完成超时：1小时
    analysisTask.steps.append(analysisStep);

    // 步骤4：采样仪排水（条件执行）
    OperationStep drainStep(AtomicOperation::SAMPLE_DRAIN);
    drainStep.targetDevices = DeviceNames::getDeviceNamesByType(DeviceType_sample);
    drainStep.description = "采样仪排水";
    drainStep.conditionKey = "need_drain";  // 需要排水的条件键
    analysisTask.steps.append(drainStep);

    defineCompositeTask(COMPOSITE_TASK_ANALYSIS, analysisTask);
}

void TaskStateMachine::defineSpikeRecoveryTask()
{
    // 优化的加标回收任务：预处理 → 打开加标阀 → 加标回收 → 关闭加标阀
    CompositeTask spikeTask("加标回收任务");
    spikeTask.description = "执行完整的加标回收测试流程";

    // 步骤1：预处理
    OperationStep preprocessStep(AtomicOperation::PREPROCESS);
    preprocessStep.targetDevices = DeviceNames::getDeviceNamesByType(DeviceType_ycl);
    preprocessStep.description = "预处理准备";
    preprocessStep.abortOnError = true;
    preprocessStep.waitTimeout = 60 * 60;  // 等待预处理完成超时：1小时
    spikeTask.steps.append(preprocessStep);

    // 步骤2：打开加标阀
    OperationStep openValveStep(AtomicOperation::PRE_SPIKE_VALVE_OPEN);
    openValveStep.targetDevices = DeviceNames::getDeviceNamesByType(DeviceType_ycl);
    openValveStep.description = "打开加标阀";
    spikeTask.steps.append(openValveStep);

    // 步骤3：加标回收核心流程
    OperationStep spikeRecoveryStep(AtomicOperation::SPIKE_RECOVERY_FULL);
    spikeRecoveryStep.targetDevices = DeviceNames::getDeviceNamesByType(DeviceType_spike);
    spikeRecoveryStep.description = "执行加标回收测试";
    spikeRecoveryStep.waitTimeout = 60 * 60 * 3;  // 等待完成超时3小时
    spikeTask.steps.append(spikeRecoveryStep);

    // 步骤4：关闭加标阀
    OperationStep closeValveStep(AtomicOperation::PRE_SPIKE_VALVE_CLOSE);
    closeValveStep.targetDevices = DeviceNames::getDeviceNamesByType(DeviceType_ycl);
    closeValveStep.description = "关闭加标阀";
    spikeTask.steps.append(closeValveStep);

    defineCompositeTask(COMPOSITE_TASK_SPIKE_RECOVERY, spikeTask);
}